package com.kayak.easysp.appsecurity;

import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.kayak.easysp.util.ErrorCodeEasysp;
import com.kayak.exception.ErrorException;
import com.kayak.kkutils.security.HMacMD5;
import com.kayak.kkutils.security.KKAES;
import com.kayak.kkweb.object.BaseErrorCode;

/**
 * 密钥加解密与签名的公共类
 * @author guancj 20160420
 * 
 * */
public class APPEncrypt {
	  public static Logger log = LoggerFactory.getLogger(APPEncrypt.class);

	  public static final String DEFAULT_MAC_METHOD = "HMACMD5";
	  public static final String DEFAULT_ENCODE_METHOD = "AES";
	  //缓存密钥为空的返回错误码
	  public static final String KEY_NULL_ERRCODE = "AEK9";

	  private static String encode(String method, String key, String msg)
	    throws ErrorException
	  {
	    if (method.equals("AES")) {
	      try {
	        KKAES kkaes = new KKAES(key);
	        return kkaes.encrypt(msg.getBytes());
	      } catch (Exception e) {
	        e.printStackTrace();
	        throw new ErrorException(ErrorCodeEasysp.ERROR_EASYSP_SYSTEMBUSY_CODE, ErrorCodeEasysp.ERROR_EASYSP_SYSTEMBUSY_MSG);
	      }
	    }
	    return "";
	  }

	  private static String encode(String key, String msg) throws ErrorException
	  {
	    return encode("AES", key, msg);
	  }

	  private static String decode(String method, String key, String msg) throws ErrorException {
	    if (method.equals("AES")) {
	      try {
	        KKAES kkaes = new KKAES(key);
	        return new String(kkaes.decrypt(msg));
	      } catch (RuntimeException e1) {
	        e1.printStackTrace();
	        throw new ErrorException(ErrorCodeEasysp.ERROR_EASYSP_SYSTEMBUSY_CODE, ErrorCodeEasysp.ERROR_EASYSP_SYSTEMBUSY_MSG);
	      }
	      catch (Exception e) {
	        e.printStackTrace();
	        throw new ErrorException(ErrorCodeEasysp.ERROR_EASYSP_SYSTEMBUSY_CODE, ErrorCodeEasysp.ERROR_EASYSP_SYSTEMBUSY_MSG);
	      }
	    }
	    return "";
	  }

	  private static String decode(String key, String msg) throws ErrorException
	  {
	    return decode("HMACMD5", key, msg);
	  }

	  /**
	   * 获取mac签名值
	   * @param key 工作密钥值
	   * 		columns 字段列表
	   * 		params 参数值
	   * 
	   * */
	  public static String getMac(String key, String columns, Map params) throws ErrorException {
		    return getMac("HMACMD5", key, columns, params);
	  }
	  
	  public static String getMac(String method, String key, String columns, Map params) throws ErrorException {
	    if (method.equals("HMACMD5")) {
	      try {
	        return HMacMD5.getHmacMd5Bytes(key.getBytes(), getMacBlock(columns, params).getBytes());
	      } catch (Exception e) {
	        e.printStackTrace();
	        throw new ErrorException(ErrorCodeEasysp.ERROR_EASYSP_SYSTEMBUSY_CODE, ErrorCodeEasysp.ERROR_EASYSP_SYSTEMBUSY_MSG);
	      }
	    }
	    return "";
	  }
	  
	  /**
	   * 获取mac块值
	   * @param columns mac签名的字段
	   * 		params  参数值
	   * */
	  private static String getMacBlock(String columns, Map params) throws ErrorException {
		  
	    String[] keys = columns.split("\\|");
	    String value = "";
	    StringBuffer macblock = new StringBuffer();
	    for (String temp : keys) {
	      value = (String)params.get(temp);
	      if (StringUtils.isBlank(value)) {
	      } else {
		      macblock.append(value.toUpperCase());
		      macblock.append(" ");
	      }
	    }

	    log.info("mac签名的字段columns:" + columns);
	    log.info("macblock块值:" + macblock.toString().trim());
	    
	    return macblock.toString().trim();
		    
	  }

	  /**
	   * 校验数据签名
	   * @param key 工作密钥
	   * 		columns 字段列表
	   * 		params 需要校验签名的数据
	   * 		mac 报文传的mac值
	   * 
	   * */
	  public static boolean checkMac(String key, String columns, Map params, String mac) throws ErrorException
	  {
	    return checkMac("HMACMD5", key, columns, params, mac);
	  }
	  
	  public static boolean checkMac(String method, String key, String columns, Map params, String mac) throws ErrorException {
	    if (method.equals("HMACMD5")) {
	      try {
	        log.info("接收到的mac值:"+mac );
	        String getMac = getMac("HMACMD5", key, columns, params);
	        log.info("计算出的mac值:"+getMac);
	        return getMac.equals(mac);
	      } catch (Exception e) {
	        e.printStackTrace();
	        throw new ErrorException(ErrorCodeEasysp.ERROR_EASYSP_SYSTEMBUSY_CODE, ErrorCodeEasysp.ERROR_EASYSP_SYSTEMBUSY_MSG);
	      }
	    }
	    return false;
	  }

	  /**
	   * 字段加密
	   * @param params 待加密的数据
	   * 		columns 需要加密的字段列表
	   * 		key 密钥
	   * */
	  public static Map encodeMap(Map params, String columns, String key) throws ErrorException {
	    return encodeMap(params, columns, "AES", key);
	  }
	  
	  public static Map encodeMap(Map params, String columns, String method, String key) throws ErrorException
	  {
	    String[] keys = columns.split("\\|");
	    String value = "";
	    StringBuffer macblock = new StringBuffer();
	    for (String temp : keys)
	    {
	      value = (String)params.get(temp);
	      if (StringUtils.isBlank(value)) {
	      } else {
		      try
		      {
		        params.put(temp, encode(method, key, value));
		      } catch (Exception e) {
		        throw new ErrorException("SE6005", 
		          BaseErrorCode.getErrorMsg("ERROR_SE6005"));
		      }
	      }
	    }

	    return params;
	  }

	  /**
	   * 字段解密
	   * @param params 待解密的数据
	   * 		columns 需要解密的字段列表
	   * 		key 密钥
	   * */
	  public static Map decodeMap(Map params, String columns, String key) throws ErrorException {
	    return decodeMap(params, columns, "AES", key);
	  }
	  
	  public static Map decodeMap(Map params, String columns, String method, String key) throws ErrorException {
	    String[] keys = columns.split("\\|");
	    String value = "";
	    StringBuffer macblock = new StringBuffer();
	    for (String temp : keys)
	    {
	      value = (String)params.get(temp);

//	      log.info("temp:"+temp);
//	      log.info("value:"+value);
	      
	      if (StringUtils.isBlank(value)) {
	    	 //无加密的字段则不处理 by guancj 20160414
	        //throw new ErrorException("1001", 
	          //BaseErrorCode.getErrorMsg("ERROR_1001"));
	      } else {
		      try
		      {
		        params.put(temp, decode(method, key, value));
		      } catch (Exception e) {
		        throw new ErrorException("SE6004", 
		          BaseErrorCode.getErrorMsg("ERROR_SE6004"));
		      }
	      }
	    }

	    return params;
	  }
	 
	  
	  
	}
	
